﻿#include "PickedDataCalculator.h"

// VTK
#include <vtkActor.h>
#include <vtkMapper.h>
#include <vtkPlanes.h>
#include <vtkUnstructuredGrid.h>
#include <vtkCellData.h>
#include <vtkIntArray.h>
#include <vtkDataArray.h>

// APP
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKKeyMouseStates.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"

// Global data
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"

// Data
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoCommand.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMeshPartVTK.h"
#include "FITK_Interface/FITKInterfaceModel/FITKUnstructuredMesh.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractSection.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKSectionAssign.h"
#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysAbsShell.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysCavity.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"

// Graph
#include "FITK_Interface/FITKVTKAlgorithm/FITKGraphActor.h"
#include "FITK_Component/FITKAcousticsVTKGraphAdaptor/FITKAcousticsVTKCommons.h"
#include "FITK_Component/FITKAcousticsVTKGraphAdaptor/FITKAcousticsVTKSharedDataManager.h"
#include "FITK_Component/FITKAcousticsVTKGraphAdaptor/FITKAcousticsVTKGraphObject3D.h"

// Filter ( Algorithm )
#include "FITK_Interface/FITKVTKAlgorithm/FITKExtractGeometry.h"

// Pick
#include "PickedData.h"

#define CellSectionIds "CellSectionIds"

namespace GraphData
{
    PickedDataCalculator::PickedDataCalculator(GraphData::PickedData* pickedData) :
        m_pickedData(pickedData)
    {
        // 初始化键盘状态监视器。
        m_keyStates = FITKAPP->getGlobalData()->getKeyMouseStates();
    }

    void PickedDataCalculator::calculate()
    {
        if (!m_pickedData)
        {
            return;
        }

        // 点选拾取方式
        //@{
        if (m_pickedData->getPickedMouseType() == PickedMouseType::PickedMouseClick)
        {
            bySingle();
        }
        //@}
        // 框选拾取方式
        //@{
        else if (m_pickedData->getPickedMouseType() == PickedMouseType::PickedMouseRubber)
        {
            byAreaPick();
        }
        //@}

        // 不管计算完成都将是否需要计算标识置为false。
        m_pickedData->calculateFinsish();

        // 排序。
        m_pickedData->sortIds();
    }

    vtkDataSet* PickedDataCalculator::getPickedDataSet()
    {
        vtkActor* actor = m_pickedData->getPickedActor();
        if (!actor)
        {
            return nullptr;
        }

        vtkMapper* mapper = actor->GetMapper();
        if (!mapper)
        {
            return nullptr;
        }

        vtkDataSet* dataSet = mapper->GetInputAsDataSet();
        return dataSet;
    }

    void PickedDataCalculator::bySingle()
    {
        // 获取拾取对象类型。
        PickedDataType pdType = m_pickedData->getPickedDataType();

        // 获取拾取时的拾取方式信息。
        GUI::GUIPickInfoStru pickInfo = m_pickedData->getPickedInfo();

        switch (pdType)
        {
        case GraphData::GeoVertPick:
        case GraphData::GeoEdgePick:
        case GraphData::GeoFacePick:
        case GraphData::GeoSolidPick:
        {
            // 几何。
            bySingleGeometry();
            return;
        }
        case GraphData::MeshCellPick:
        {
            int cellDim = -1;
            if (pickInfo._pickObjType == GUI::GUIPickInfo::POBJMeshCell1D)
            {
                cellDim = 1;
            }
            else if (pickInfo._pickObjType == GUI::GUIPickInfo::POBJMeshCell2D)
            {
                cellDim = 2;
            }
            else if (pickInfo._pickObjType == GUI::GUIPickInfo::POBJMeshCell3D)
            {
                cellDim = 3;
            }

            // 网格单元。
            switch (pickInfo._pickMethod)
            {
            case GUI::GUIPickInfo::PickMethod::PMSingle:
            case GUI::GUIPickInfo::PickMethod::PMIndividually:
            {
                // 点选单个网格单元。
                bySingleMeshCell(cellDim);
                return;
            }
            case GUI::GUIPickInfo::PickMethod::PMByMeshProp:
            {
                // 点选单个网格单元获取整片相同属性的网格区域。
                byPropMeshCell(cellDim);
                return;
            }
            default:
                break;
            }

            return;
        }
        case GraphData::DiscNodePick:
        {
            // SEA节点。
            byDiscNodes();
            return;
        }
        case GraphData::SEAShellPick:
        case GraphData::SEACavityPick:
        {
#if SUBSYSTEM_MERGE
            // 点选 SEA壳（板）& SEA声腔 处理拾取数据。
            byMergedObjectSEASubSys();
            return;
        }
        case GraphData::JuncLinePick:
        case GraphData::JuncAreaPick:
        {
            // 点选 SEA连接线 & SEA连接区域 处理拾取数据。
            byMergedObject();
            return;
        }
        case GraphData::FEFacePick:
        case GraphData::FEStructureShellPick:
        case GraphData::FEStructureBeamPick:
        case GraphData::FEAcousticPick: {
            //点选 FE面 & FE结构 & FE声腔
            byMergedObjectFESubSys();
            break;
        }
#endif
        case GraphData::SEABeamPick:
        {
            // 点选 SEA梁 处理拾取数据。
            bySingleSEABeam();
            return;
        }
        case GraphData::LoadPointForcePick:
        case GraphData::LoadPowerPick:
        case GraphData::LoadConstraintPick:
        case GraphData::LoadImportPick:
        case GraphData::LoadExcForMomPick:
        case GraphData::LoadMonopolePick: {
            //载荷点选
            bySingleLoad();
            return;
        }
        case GraphData::FESensorPick: {
            //传感器点选
            bySingleSensor();
            return;
        }
        case GraphData::SEASemiInfFluidPick:
        case GraphData::JuncPointPick:
            // 点选 SEA梁 & SEA半无限流体 & SEA连接点 无需处理拾取数据。
        default:
            break;
        }
    }

    void PickedDataCalculator::byMergedObject()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        int dataId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SHAPE);
        if (dataId == -1)
        {
            return;
        }

        // 保存数据。
        m_pickedData->savePickedDataObjId(dataId);
    }

    void PickedDataCalculator::byMergedObjectSEASubSys()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        int dataId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SHAPE);
        int faceId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_FACE);
        int elemId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::MT_Element);
        if (dataId == -1)
        {
            return;
        }

        // 保存数据。
        m_pickedData->savePickedDataObjId(dataId);

        // 保存SEA面数据。
        PickedFaceData pFace;
        pFace.FaceId = faceId;
        pFace.ElementId = elemId;
        m_pickedData->getPickedSEAFaces().push_back(pFace);
    }

    void PickedDataCalculator::byMergedObjectFESubSys()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        int dataId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SHAPE);
        int elemId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::MT_Element);
        if (dataId == -1)
        {
            return;
        }

        // 保存数据。
        m_pickedData->savePickedDataObjId(dataId);

        // 保存SEA面数据。
        PickedFaceData pFace;
        pFace.ElementId = elemId;
        m_pickedData->getPickedSEAFaces().push_back(pFace);
    }

    void PickedDataCalculator::bySingleLoad()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        if (!gobj){
            return;
        }

        gobj->highlight();
        int dataId = gobj->getDataId();

        // 保存数据。
        m_pickedData->savePickedDataObjId(dataId);
    }

    void PickedDataCalculator::bySingleSensor()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        if (!gobj) {
            return;
        }

        gobj->highlight();
        int dataId = gobj->getDataId();

        // 保存数据。
        m_pickedData->savePickedDataObjId(dataId);
    }

    void PickedDataCalculator::byAreaPick()
    {
        // 获取拾取平面。
        vtkPlanes* pickPlanes = m_pickedData->getPickPlanes();
        if (!pickPlanes)
        {
            return;
        }

        // 获取拾取对象类型。
        PickedDataType pdType = m_pickedData->getPickedDataType();

        // 获取拾取时的拾取方式信息。
        GUI::GUIPickInfoStru pickInfo = m_pickedData->getPickedInfo();

        switch (pdType)
        {
        case GraphData::GeoVertPick:
        case GraphData::GeoEdgePick:
        case GraphData::GeoFacePick:
        case GraphData::GeoSolidPick:
        {
            // 几何。
            byAreaGeometry();
            return;
        }
        case GraphData::MeshCellPick:
        {
            int cellDim = -1;
            if (pickInfo._pickObjType == GUI::GUIPickInfo::POBJMeshCell1D)
            {
                cellDim = 1;
            }
            else if (pickInfo._pickObjType == GUI::GUIPickInfo::POBJMeshCell2D)
            {
                cellDim = 2;
            }
            else if (pickInfo._pickObjType == GUI::GUIPickInfo::POBJMeshCell3D)
            {
                cellDim = 3;
            }

            // 网格单元。
            byAreaMeshCell(cellDim);
            return;
        }
        case GraphData::DiscNodePick:
            // SEA节点无法进行框选拾取。
            return;
        case GraphData::SEAShellPick:
        case GraphData::SEACavityPick:
        {
#if SUBSYSTEM_MERGE
            // 框选 SEA壳（板）& SEA声腔 处理拾取数据。
            // byMergedObjectSEASubSys();
            return;
        }
        case GraphData::JuncLinePick:
        case GraphData::JuncAreaPick:
            // 框选 SEA连接线 & SEA连接区域 处理拾取数据。
            // byMergedObject();
            return;
#endif
        case GraphData::SEABeamPick:
        case GraphData::SEASemiInfFluidPick:
        case GraphData::JuncPointPick:
            // 框选 SEA梁 & SEA半无限流体 & SEA连接点 无需处理拾取数据。
        default:
            break;
        }
    }

    void PickedDataCalculator::byDiscNodes()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        // 获取SEA模型。       
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)
        {
            return;
        }

        // 获取SEA节点列表。
        Acoustics::FITKAcousticsDiscNodeList* nodes = discModel->getNodes();
        if (!nodes)
        {
            return;
        }

        // 根据拾取对象索引获取拾取到的节点。
        int nId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_VERTEX);

        // 获取键盘按下状态。
        bool ctrlPressed = m_keyStates->keyPressed(Qt::Key::Key_Control);
        bool shiftPressed = m_keyStates->keyPressed(Qt::Key::Key_Shift);

        // 保存节点ID与节点类型。
        Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode ssNode;
        ssNode._id = nId;

        // Ctrl与Shift均未按下则为起始点。
        if (!ctrlPressed && !shiftPressed)
        {
            ssNode._type = Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Start;
        }
        // 仅Ctrl按下则为路径点
        else if (ctrlPressed && !shiftPressed)
        {
            ssNode._type = Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Path;
        }
        // 仅Shift按下则为拐点
        else if (!ctrlPressed && shiftPressed)
        {
            ssNode._type = Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Corner;
        }
        // Ctrl与Shift均按下则为结束点。
        else if (ctrlPressed && shiftPressed)
        {
            ssNode._type = Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Finish;
        }

        // 追加节点。
        m_pickedData->getPickedDiscNodes().push_back(ssNode);
    }

    void PickedDataCalculator::bySingleGeometry()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        // 获取几何模型命令。       
        Interface::FITKAbsGeoCommand* geoCmd = dynamic_cast<Interface::FITKAbsGeoCommand*>(gobj->getDataOject());
        if (!geoCmd)
        {
            return;
        }

        // 获取虚拓扑ID。
        int vTopoId = -1, vTopoIndex = -1;

        // 根据拾取数据类型进行不同数据获取。
        switch (m_pickedData->getPickedDataType())
        {
        case PickedDataType::GeoVertPick:
            vTopoId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_VERTEX);
            vTopoIndex = gobj->getVirTopoIndexByShapeId(vTopoId, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_VERTEX);
            break;
        case PickedDataType::GeoEdgePick:
            vTopoId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_EDGE);
            vTopoIndex = gobj->getVirTopoIndexByShapeId(vTopoId, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_EDGE);
            break;
        case PickedDataType::GeoFacePick:
            vTopoId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_FACE);
            vTopoIndex = gobj->getVirTopoIndexByShapeId(vTopoId, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_FACE);
            break;
        case PickedDataType::GeoSolidPick:
            vTopoId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SOLID);
            vTopoIndex = gobj->getVirTopoIndexByShapeId(vTopoId, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SOLID);
            break;
        default:
            return;
        }        

        // 追加几何虚拓扑ID。
        if (vTopoId != -1)
        {
            m_pickedData->getPickedIds().push_back(vTopoId);
            //添加虚拓扑索引
            m_pickedData->appendPickedOtherId(vTopoId, vTopoIndex);
        }
    }

    void PickedDataCalculator::bySingleMeshCell(int cellDim)
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        // 获取网格部件数据。
        AbaqusData::FITKAbaqusPart* part = dynamic_cast<AbaqusData::FITKAbaqusPart*>(gobj->getDataOject());
        if (!part)
        {
            return;
        }

        // 获取部件网格数据。
        Interface::FITKAbaMeshPartVTK* partMesh = part->getMesh();
        if (!partMesh)
        {
            return;
        }
        //获取网格
        vtkUnstructuredGrid* grid = partMesh->getGrid();
        if (grid == nullptr) {
            return;
        }
        //获取section参数组
        vtkDataArray* sectionIdArray = grid->GetCellData()->GetArray(CellSectionIds);

        // 获取网格单元ID。
        int elementId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::MT_Element);

        // 获取单元维度。
        Interface::FITKAbstractElement* ele = partMesh->getElementByID(elementId);
        if (!ele)
        {
            return;
        }

        if (cellDim != ele->getElementDim() && cellDim != -1)
        {
            return;
        }

        // 追加单元ID。
        m_pickedData->getPickedIds().push_back(elementId);
        //追加sectionID
        if (sectionIdArray) {
            int sectionID = sectionIdArray->GetComponent(elementId, 0);
            m_pickedData->appendPickedOtherId(elementId, sectionID);
        }
    }  

    void PickedDataCalculator::bySingleSEABeam()
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        int dataId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SHAPE);
        int segentIndex = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_EDGE);
        if (dataId == -1)
        {
            return;
        }

        // 保存数据。
        m_pickedData->savePickedDataObjId(dataId);

        // 保存SEA点索引数据。
        m_pickedData->getPickedIds().push_back(segentIndex);
    }

    void PickedDataCalculator::byAreaGeometry()
    {
        // 获取拾取平面。
        vtkPlanes* pickPlanes = m_pickedData->getPickPlanes();
        vtkActor* actor = m_pickedData->getPickedActor();
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        if (!gobj || !pickPlanes || !actor)
        {
            return;
        }

        // 获取拾取数据集。
        vtkDataSet* dataSet = actor->GetMapper()->GetInputAsDataSet();
        if (!dataSet)
        {
            return;
        }

        int len = 0;
        Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum sType;

        // 根据拾取数据类型进行不同数据获取。
        switch (m_pickedData->getPickedDataType())
        {
        case PickedDataType::GeoVertPick:
            len = gobj->getNumberOf(Exchange::FITKAcousticsVTKCommons::ShapeType::ModelVertex);
            sType = Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_VERTEX;
            break;
        case PickedDataType::GeoEdgePick:
            len = gobj->getNumberOf(Exchange::FITKAcousticsVTKCommons::ShapeType::ModelEdge);
            sType = Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_EDGE;
            break;
        case PickedDataType::GeoFacePick:
            len = gobj->getNumberOf(Exchange::FITKAcousticsVTKCommons::ShapeType::ModelFace);
            sType = Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_FACE;
            break;
        case PickedDataType::GeoSolidPick:
            len = gobj->getNumberOf(Exchange::FITKAcousticsVTKCommons::ShapeType::ModelSolid);
            sType = Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::STA_SOLID;
            break;
        default:
            return;
        }

        if (len == 0)
        {
            return;
        }

        // 提取数据。
        vtkSmartPointer<FITKExtractGeometry> extractor = vtkSmartPointer<FITKExtractGeometry>::New();
        extractor->SetImplicitFunction(pickPlanes);
        extractor->SetInputData(dataSet);
        extractor->Update();

        // 追加几何面ID。
        const QList<int> cellsIndice = extractor->getSelectOriginalCells();

        // 被拾取形状编号。
        QVector<int> shapeIds;

        // 预处理拾取单元数据。（加速判断拾取子Id包含关系）
        int nCells = dataSet->GetNumberOfCells();
        QVector<int> cellPickedFlags;
        cellPickedFlags.resize(nCells);
        cellPickedFlags.fill(0);
        //存储形状数据id与形状虚拓扑索引拓扑关系
        QHash<int, int> shapeIdAndVirTopoIndex = {};

        // 获取形状数据Id。
        for (const int & index : cellsIndice)
        {
            int id = gobj->getShapeIdByVTKCellId(index, sType);
            
            if (!shapeIds.contains(id)){
                shapeIds.push_back(id);
            }
            
            if (index < cellPickedFlags.size()) {
                cellPickedFlags[index] = 1;
            }

            //存储虚拓扑与虚拓扑索引关系
            int virTopoIndex = gobj->getVirTopoIndexByShapeId(id, sType);
            shapeIdAndVirTopoIndex.insert(id, virTopoIndex);
        }

        // 保存拾取数据。
        for (int i = 0; i < shapeIds.count(); i++)
        {
            int & shapeId = shapeIds[i];

            // 检测当前几何数据是否完全被选中。
            QVector<int> subIds = gobj->getVTKCellIdsByShapeId(shapeId, sType);

            bool isFullPicked = true;
            for (const int & id : subIds)
            {
                isFullPicked &= (cellPickedFlags[id] == 1);
            }

            // 完全选中则视为被框选。
            if (isFullPicked && !m_pickedData->getPickedIds().contains(shapeId))
            {
                //存储拾取形状id
                m_pickedData->getPickedIds().push_back(shapeId);
                //存储拾取形状id与形状虚拓扑索引对应关系
                m_pickedData->appendPickedOtherId(shapeId, shapeIdAndVirTopoIndex.value(shapeId));
            }
        }

        // 清除缓存。
        shapeIds.clear();
    }

    void PickedDataCalculator::byAreaMeshCell(int cellDim)
    {
        // 获取拾取平面。
        vtkPlanes* pickPlanes = m_pickedData->getPickPlanes();
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        if (!gobj || !pickPlanes)
        {
            return;
        }

        // 获取部件数据。
        AbaqusData::FITKAbaqusPart* part = dynamic_cast<AbaqusData::FITKAbaqusPart*>(gobj->getDataOject());
        if (!part)
        {
            return;
        }

        // 获取部件网格数据。
        Interface::FITKAbaMeshPartVTK* partMesh = part->getMesh();
        if (!partMesh)
        {
            return;
        }

        // 获取当前拾取数据的原始数据集。
        vtkDataSet* dataSet = partMesh->getGrid();
        if (!dataSet)
        {
            return;
        }
        //获取section参数组
        vtkDataArray* sectionIdArray = dataSet->GetCellData()->GetArray(CellSectionIds);
        // 提取数据。
        vtkSmartPointer<FITKExtractGeometry> extractor = vtkSmartPointer<FITKExtractGeometry>::New();
        extractor->SetImplicitFunction(pickPlanes);
        extractor->SetInputData(dataSet);
        extractor->Update();

        // 追加单元ID。
        const QList<int> cellsIndice = extractor->getSelectOriginalCells();
        for (const int & index : cellsIndice)
        {
            int elementId = partMesh->getEleIDByIndex(index);

            // 获取单元维度。
            Interface::FITKAbstractElement* ele = partMesh->getElementByID(elementId);
            if (!ele)
            {
                continue;
            }

            if (cellDim != ele->getElementDim() && cellDim != -1)
            {
                continue;
            }

            // 追加单元ID。
            m_pickedData->getPickedIds().push_back(elementId);
            //追加sectionID
            if (sectionIdArray) {
                int sectionID = sectionIdArray->GetComponent(elementId, 0);
                m_pickedData->appendPickedOtherId(elementId, sectionID);
            }
        }
    }

    void PickedDataCalculator::byPropMeshCell(int cellDim)
    {
        Exchange::FITKAcousticsVTKGraphObject3D* gobj = m_pickedData->getPickedGraphObejct();
        int index = m_pickedData->getPickedIndex();
        if (!gobj || index < 0)
        {
            return;
        }

        // 获取网格部件数据。
        AbaqusData::FITKAbaqusPart* part = dynamic_cast<AbaqusData::FITKAbaqusPart*>(gobj->getDataOject());
        if (!part)
        {
            return;
        }

        // 获取FE模型与相关管理器。
        Acoustics::FITKAcousticsDiscModel* discModel = FITKGLODATA->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)
        {
            return;
        }

        // 获取区域指派管理器。
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        if (!feModel)
        {
            return;
        }

        Interface::FITKAbstractSectionManager* secMgr = feModel->getSectionManager();
        Interface::FITKSectionAssignManager* assMgr = part->getSectionAssignManager();
        Interface::FITKComponentManager* setMgr = part->getComponentManager();
        if (!secMgr || !assMgr || !setMgr)
        {
            return;
        }

        // 获取部件网格数据。
        Interface::FITKAbaMeshPartVTK* partMesh = part->getMesh();
        if (!partMesh)
        {
            return;
        }

        //获取网格
        vtkUnstructuredGrid* grid = partMesh->getGrid();
        if (grid == nullptr) {
            return;
        }
        //获取section参数组
        vtkDataArray* sectionIdArray = grid->GetCellData()->GetArray(CellSectionIds);

        // 获取点选到的网格单元ID。
        int srcElementId = gobj->getShapeIdByVTKCellId(index, Exchange::FITKAcousticsVTKCommons::ShapeMeshAbsEnum::MT_Element);
        if (srcElementId <= 0)
        {
            return;
        }

        // 获取包含该单元的单元集合成员。
        QList<int> elementIds;

        // 获取全部指派。
        int nAssign = assMgr->getDataCount();
        for (int i = 0; i < nAssign; i++)
        {
            Interface::FITKSectionAssign* assign = assMgr->getDataByIndex(i);
            if (!assign)
            {
                continue;
            }

            // 获取指派的集合ID。
            int setId = assign->getModelID();
            Interface::FITKAbstractModelComponent* set = setMgr->getDataByID(setId);

            // 获取集合。
            Interface::FITKModelSet* modelSet = dynamic_cast<Interface::FITKModelSet*>(set);
            if (!modelSet)
            {
                continue;
            }

            // 仅获取单元集。
            QList<Interface::FITKModelSet*> sets;
            modelSet->getAbsoluteSet(sets, Interface::FITKModelEnum::FITKModelSetType::FMSElem);

            // 查找单元。
            for (Interface::FITKModelSet* set : sets)
            {
                QList<int> members = set->getAbsoluteMember();
                if (members.contains(srcElementId))
                {
                    elementIds << members;
                    break;
                }
            }
        }

        // 追加单元ID。
        for (const int & elementId : elementIds)
        {
            // 获取单元维度。
            Interface::FITKAbstractElement* ele = partMesh->getElementByID(elementId);
            if (!ele)
            {
                continue;
            }

            if (cellDim != ele->getElementDim() && cellDim != -1)
            {
                continue;
            }

            m_pickedData->getPickedIds().push_back(elementId);
            //追加sectionID
            if (sectionIdArray) {
                int sectionID = sectionIdArray->GetComponent(elementId, 0);
                m_pickedData->appendPickedOtherId(elementId, sectionID);
            }
        }
    }
}